"""
waitpos.py:

This script may be used to wait for a given motor/parameter to
reach and hold a target value. It works for both motors and parameters

	
The syntax of the waitpos command is:

waitpos motor_or_parameter_name target_min_value target_max_value hold_time [max_time]

where 
	motor_or_parameter_name is the name of the SPICE motor or parameter to be monitored
	target_min_value is the minimum target value for the SPICE motor or parameter to be considered in position
	target_max_value is the maximum target value for the SPICE motor or parameter to be considered in position
	hold_time is the time in seconds that the target is required to be in-position before returning
	max_time is the maximum time in seconds to wait
	
	Note that max_time is an optional parameter. If not supplied, there is no maximum wait time.
 
Example:

waitpos.py tsample 34.99 35.01 15.0
(wait for tsample to be at 35.0 +/- 0.01 for 15 seconds; wait forever if necessary)


Author: Ray Gregory
"""

import sys
import PySpice
from time import sleep

insufficient_arguments_error_message = """Error. The waitpos script requires at least 4 arguments.

	
The syntax of the waitpos command is:

waitpos motor_or_parameter_name target_min_value target_max_value hold_time [max_time]

where 
	motor_or_parameter_name is the name of the SPICE motor or parameter to be monitored
	target_min_value is the minimum target value for the SPICE motor or parameter to be considered in position
	target_max_value is the maximum target value for the SPICE motor or parameter to be considered in position
	hold_time is the time in seconds that the target is required to be in-position before returning
	max_time is the maximum time in seconds to wait
	
	Note that max_time is an optional parameter. If not supplied, there is no maximum wait time.
 
Example:

waitpos.py tsample 34.99 35.01 15.0
(wait for tsample to be within the rnage of 34.99 to 35.01 for 15 seconds; wait forever if necessary)

"""


if len(sys.argv) < 5:
    raise ValueError, insufficient_arguments_error_message
	
target_axis = sys.argv[1]
target_min_value = float(sys.argv[2])
target_max_value = float(sys.argv[3])
hold_time = float(sys.argv[4])

if len(sys.argv) > 5:
	max_time = float(sys.argv[5])
	max_time_description = "a maximum waiting time of {0} seconds".format(max_time)
else:
	max_time = -1.0
	max_time_description = "no maximum waiting time"
	

print "Waiting for {0}\nto be within the range of {1} to {2}\nfor {3} seconds,\nwith {4}...\n".format(target_axis, target_min_value, target_max_value, hold_time, max_time_description)

# Set an incremental wait time to a tenth of the target hold time with a minimum incremental wait time of 1 second.
incremental_wait_time = max(1.0, hold_time/10.0)

#print "The incremental wait time is", incremental_wait_time, "seconds.\n"

cur_wait_time = 0.0
in_position_time = 0.0
cur_in_position = False
hold_condition_met = False
keep_waiting = True

# Wait for a number of incremental wait times checking to see if the
# motor/parameter is in position. Accumulate the amount of time in
# position and break out if hold time reached.

while keep_waiting:

	# Get current position
	current_value=PySpice.getpos(target_axis)
	
	# Check to see if in position
	prev_in_position = cur_in_position
	cur_in_position = current_value >= target_min_value and current_value <= target_max_value
	
	# Update time spent in position.
	if cur_in_position:
		if prev_in_position:
			in_position_time += incremental_wait_time
			if in_position_time >= hold_time:
				hold_condition_met = True
				break
		else:
			# Start over.
			in_position_time = 0.0
	else:
		# Start over required.
		in_position_time = 0.0
    
	#print "In position:", cur_in_position, ", in_position_time:", in_position_time, "(seconds), cur_wait_time:", cur_wait_time, "(seconds)."
	
	# Wait and update keep_waiting.
	sleep(incremental_wait_time)
	cur_wait_time += incremental_wait_time
	if max_time > 0:
		keep_waiting = cur_wait_time < max_time
	else:
		keep_waiting = True;

if hold_condition_met:
	print "Finished. Hold Condition met."
else:
	print "Finished. Hold Condition NOT met. Maximum time exhausted."




